#include "Node.hpp"

#include <sstream>

int Node::cardinal = 0;

Node::Node():
        _rightSibling(NULL)
{
    _x = 0;
    _y = 0;
    _type = ABSTRACT;
    _relationType = NONE;
    std::ostringstream oss;
    oss << "Task " << Node::cardinal++;
    _name = oss.str();
    _iterative = false;
    _optional = false;
    _father = NULL;
}

Node::Node(const Node& orig):
    _father(NULL),
    _rightSibling(NULL),
    _children(orig._children.size()),
    _type(orig._type),
    _relationType(orig._relationType),
    _name(orig._name),
    _x(orig._x), _y(orig._y)
{
    for(unsigned int i = 0; i < orig._children.size(); i++)
    {
        _children[i] = new Node(*orig._children[i]);
        _children[i]->_father = this;
        if(i > 0)
            _children[i - 1]->_rightSibling = _children[i];
    }
}

Node::~Node()
{
    for(unsigned int i = 0; i < _children.size(); i++)
        delete _children[i];
}

void Node::moveGraphically(int dx, int dy)
{
    _x += dx;
    _y += dy;
}

void Node::addChild(Node* newChild)
{
    newChild->_father = this;
    newChild->_type = _type;
    if(_children.size() > 0)
        _children.back()->_rightSibling = newChild;
    _children.push_back(newChild);
    redrawSubTree();
}

void Node::addLeftSibling(Node* newLeftSibling)
{
    if(_father)
    {
        newLeftSibling->_father = _father;
        newLeftSibling->_rightSibling = this;
        newLeftSibling->_type = _father->_type;
        _father->_children.push_back(NULL);
        for(unsigned int i = _father->_children.size() - 1; i > 0; i--)
        {
            _father->_children[i] = _father->_children[i - 1];
            if(_father->_children[i] == this)
            {
                _father->_children[i - 1] = newLeftSibling;
                if(i > 1)
                    _father->_children[i - 2]->_rightSibling = newLeftSibling;
                break;
            }
        }
        _father->redrawSubTree();
    }
}

void Node::setName(const std::string& name)
{
    _name = name;
}

const std::string& Node::getName() const
{
    return _name;
}

void Node::setType(NodeType nodeType)
{
    _type = nodeType;
}

void Node::setRelationType(RelationType rType)
{
    _relationType = rType;
}

Node::NodeType Node::getType() const
{
    return _type;
}

Node::RelationType Node::getRelationType() const
{
    return _relationType;
}

bool Node::isIterative() const
{
    return _iterative;
}

bool Node::isOptional() const
{
    return _optional;
}

const std::vector<Node*>& Node::getChildren() const
{
    return _children;
}

int Node::getX() const
{
    return _x;
}

int Node::getY() const
{
    return _y;
}

Node* const Node::getFather() const
{
    return _father;
}

Node* const Node::getRightSibling() const
{
    return _rightSibling;
}

void Node::setIterative()
{
    _iterative = !_iterative;
}

void Node::setOptional()
{
    _optional = !_optional;
}

/*
  Position graphique la plus a gauche, en haut, en bas et la plus a droite d'un sous arbre.
  */
void Node::getExtremes(int* minX, int* minY, int* maxX, int* maxY) const
{
    int subTreeMinX = 0, subTreeMinY = 0,
        subTreeMaxX = 0, subTreeMaxY = 0;
    *minX = 0;
    *minY = 0;
    *maxX = 0;
    *maxY = 0;

    for(unsigned int i = 0; i < _children.size(); i++)
    {
        _children[i]->getExtremes(&subTreeMinX, &subTreeMinY,
                                  &subTreeMaxX, &subTreeMaxY);
        if(*minX > subTreeMinX)
            *minX = subTreeMinX;
        if(*minY > subTreeMinY)
            *minY = subTreeMinY;
        if(*maxX < subTreeMaxX)
            *maxX = subTreeMaxX;
        if(*maxY < subTreeMaxY)
            *maxY = subTreeMaxY;
    }

    *minX += _x;
    *minY += _y;
    *maxX += _x;
    *maxY += _y;

    if(*minX > _x)
        *minX = _x;
    if(*minY > _y)
        *minY = _y;
    if(*maxX < _x)
        *maxX = _x;
    if(*maxY < _y)
     *maxY = _y;
}

int Node::redrawSubTree()
{
    if(_children.size() == 0)
        return 1;
    else
    {
        int* sizes = new int[_children.size()];
        int totalWidth = 0;

        for(unsigned int i = 0; i < _children.size(); i++)
        {
            sizes[i] = _children[i]->redrawSubTree();
            totalWidth += sizes[i];
        }

        int currentX = 0;
        for(unsigned int i = 0; i < _children.size(); i++)
        {
            _children[i]->_x = - (totalWidth * BRODIST) / 2
                             + currentX + (sizes[i] * BRODIST) / 2;
            _children[i]->_y = DADDIST;

            currentX += sizes[i] * BRODIST;
        }
        return totalWidth;
    }
}

#include <sstream>


void Node::toString(std::ostringstream& s){

s <<"\""+this->_name +"\"";
s << this->getX();
s <<" ";
s << this->getY();
s <<" ";
s << this->getType();
s <<" ";
s << this->isIterative();
s <<" ";
s << this->isOptional();
s << "{";
int i;
for (i = 0 ; i < _children.size() ; i++){
    s <<"\n";
    _children[i]->toString(s);
    s << ", ";
}
s <<"\n";
s << "}";
}

#include <iostream>
#include <fstream>
#include <string>
void Node::open(std::ifstream& i){
//    char a;
//     while (1==1){
//         cout << i.get();
//     }

//    i.get(a);//lit "
//    i.get(a);
//    _name = "";
//    while (a != '\"'){
//        _name = _name + a;
//        cout << "pas trouvé" << endl;
//    }
//    cout << _name ;
//    cout << "à été lu"<<endl;

}

